//        
//          
//  . : PE_Kill
//----------------------------------------------------------------------------------
var call_VM
var call_cur
//----------------------------------------------------------------------------------
var scan_start
var scan_end
//----------------------------------------------------------------------------------
var base_old
var base_new
//----------------------------------------------------------------------------------
var table_of_jcc
var table_of_jcc_base
var type_of_jcc
//----------------------------------------------------------------------------------
var emule_swich
var emule_last_jamp

var emule_type_jcc_temp
var emule_jcc_temp

var emule_type_jcc
var emule_jcc

var emule_cmp_size
var emule_cmp_get_arg1
var arg1_num
var arg1_display

var emule_cmp_get_arg2
var arg2_num
var arg2_display

var emule_type_cmp
var type_of_cmp
var emule_cmp

var emule_cmp_jcc
var emule_cmp_type_jcc
//----------------------------------------------------------------------------------
var str1
var str2
var str3
//----------------------------------------------------------------------------------
var oep
var temp
var Info
var addr_cur
var iter
var trace_call
//----------------------------------------------------------------------------------
log ""
log "____________________________________"
log ""
log "Virtual Machine Rebuilder by PE_Kill"
log "____________________________________"
log ""
log "Inicialize..."
//jmp @init_hand
  ////////////////////////////////////////////////////////////////////////////////////////
  //  								//
  ////////////////////////////////////////////////////////////////////////////////////////
mov oep,eip			//  eip   
mov addr_cur,eip		//   eip
and addr_cur,FFFFF000		//   1000h
mov eip,addr_cur		//    
mov scan_start,eip		//!       
mov base_old,eip		//!      
  //====================================================================================//
  //   ,   VM.      //
  // ,     1000h.    .				//
  //====================================================================================//
@init_find_VM_call:		
  find addr_cur,#E8#		//   "call"
    cmp $RESULT,0		//   ?
    je ERR_VM_CALL_NOT_FOUND	//  :(     :(    
  mov addr_cur,$RESULT		// !     
  inc addr_cur			//       VM ( E8)
  mov call_VM,[addr_cur]	//      VM
  add call_VM,addr_cur		//    call_VM
  add call_VM,4			//!   .
  mov call_cur,call_VM		//   .      
  and call_cur,00000FFF		//   5 .   
  cmp call_cur,00000000		//     1000h ,    ,    call_VM
jne @init_find_VM_call		//   
//end @init_find_VM_call
  //====================================================================================//
dec addr_cur			//     call_VM
mov eip,addr_cur		//      call_VM
inc addr_cur			//    ,    call_VM    
mov trace_call,eip		//      
sti				// Step into.    .
//======================================================================================//
// call_VM    ,      .//
//     ,         VM.   	//
//   VM    .       , 	//
//       (  )      //
//  300h (   VM)							//
//======================================================================================//
mov iter,0			//  
@init_trace_prefix:		
  inc iter			//   1
  cmp iter,300			//  300- ?
  je @init_find_VM_call		// ,   .
//!![ ,          ]!!//
//!![  ,        .	 ]!!//
  mov call_cur,eip		//   
  sti				//   
  mov temp,[esp]		//    
  sub temp,2			//  2, ,     : call exx, .. 2 
  cmp temp,call_cur		//       -2
jne @init_trace_prefix		//  ?      
//and @init_trace_prefix
//======================================================================================//

//======================================================================================//
//       ,    ,	//
//    .          	//
//     .    	//
//   .     ,    111,   	//
//  VM    ,  .    .		//
//======================================================================================//
mov iter,eip			//  eip
mov addr_cur,eip		//  eip
@init_find_error111:		//  ,   111
  find addr_cur,#68#		//  PUSH XXXXXXXX
    cmp $RESULT,0		//  ?
    je @ERR_INIT_FAILED		//    
  mov addr_cur,$RESULT		//    PUSH'a
  inc addr_cur			//   PUSH
  mov call_cur,[addr_cur]	// , ,    
  mov temp,[call_cur]		//   ,   ,      "111"
  cmp temp,0D313131		// ,   
jne @init_find_error111		// ,   ,  
//end @init_find_error111

@init_find_emulate_instr:	//    ,     call
  dec addr_cur			//     ,     ( )
  cmp addr_cur,iter		// ,     ,  
  je @ERR_INIT_FAILED		//  ,    
  mov temp,[addr_cur]		// ,   
  and temp,FF000000		//   ,  
  cmp temp,E8000000		//      call
jne @init_find_emulate_instr	//   ,  
//end @init_find_emulate_instr
add addr_cur,3			//    
bp addr_cur			//      
run				//  
bc addr_cur			//    
cmp eip,addr_cur		//    
  jne @ERR_INIT_FAILED		//  ,    
sti				// Step into.   .
//======================================================================================//

//======================================================================================//
//  :									//
// SUB AL,2										//
// JB SHORT 									//
// JE SHORT 									//
//     () ()				//
//======================================================================================//

find eip,#2C027212743D#		//  
cmp $RESULT,0			// ?
je @ERR_INIT_FAILED		// ,    
bp $RESULT			// !     
run				//  
bc $RESULT			//    
cmp eip,$RESULT			//    
  jne @ERR_INIT_FAILED		//  ,    
mov emule_swich,eip		//!,    
find eip,#FF6020#		//    JMP DWORD PTR DS:[EAX+20]
cmp $RESULT,0			// ?
je @ERR_INIT_FAILED		// ,    
add eip,16			//   16   (  JB SHORT )
bp $RESULT			//     
run				//  
bc $RESULT			//    
cmp eip,$RESULT			//    
  jne @ERR_INIT_FAILED		//  ,    
mov emule_last_jamp,eax		//   eax
add emule_last_jamp,20		// ...
mov emule_last_jamp,[emule_last_jamp]
mov eip,trace_call
bp emule_swich
run
bc emule_swich
add eip,43
@init_find_emule_type_jcc:
  mov temp,eip
  sti
  mov call_cur,[esp]
  mov addr_cur,call_cur
  sub call_cur,2
  cmp temp,call_cur
  jne @init_find_emule_type_jcc
bp addr_cur
run
bc addr_cur
mov emule_type_jcc,eip			//!!!!
find eip,#84C07417#
  cmp $RESULT,0
  je @ERR_INIT_FAILED
mov emule_jcc,$RESULT

mov eip,trace_call
bp emule_swich
run
bc emule_swich
add eip,90
@init_find_emule_cmp:
  mov temp,eip
  sti
  mov call_cur,[esp]
  mov addr_cur,call_cur
  sub call_cur,5
  cmp temp,call_cur
jne @init_find_emule_cmp
bp addr_cur
mov iter,0
@init_find_emule_cmp_get_arg1:
  mov temp,eip
  sti
  mov call_cur,[esp]
  mov addr_cur,call_cur
  sub call_cur,2
  cmp temp,call_cur
jne @init_find_emule_cmp_get_arg1
bp addr_cur
run
bc addr_cur
inc iter
cmp iter,2
jb @init_find_emule_cmp_get_arg1
mov emule_cmp_get_arg1,eip		//!!!!

mov iter,0
@init_find_emule_cmp_get_arg2:
  mov temp,eip
  sti
  mov call_cur,[esp]
  mov addr_cur,call_cur
  sub call_cur,5
  cmp temp,call_cur
  jne @init_arg1_ret
    bp addr_cur
    run
    bc addr_cur
  @init_arg1_ret:
  add call_cur,3
  cmp temp,call_cur
jne @init_find_emule_cmp_get_arg2
bp addr_cur
run
bc addr_cur
inc iter
cmp iter,2
jb @init_find_emule_cmp_get_arg2
mov emule_cmp_get_arg2,eip		//!!!!

@init_find_emule_type_cmp:
  mov temp,eip
  sti
  mov call_cur,[esp]
  mov addr_cur,call_cur
  sub call_cur,5
  cmp temp,call_cur
  jne @init_arg2_ret
    bp addr_cur
    run
    bc addr_cur
  @init_arg2_ret:
  add call_cur,3
  cmp temp,call_cur
jne @init_find_emule_type_cmp
bp addr_cur
run
bc addr_cur
sti
mov emule_type_cmp,eip			//!!!!
mov eax,4
run
bc eip

@init_find_emule_cmp_type_jcc:
  mov temp,eip
  sti
  mov call_cur,[esp]
  mov addr_cur,call_cur
  sub call_cur,2
  cmp temp,call_cur
jne @init_find_emule_cmp_type_jcc
bp addr_cur
run
bc addr_cur
mov emule_cmp_type_jcc,eip		//!!!!
find eip,#84C07417#
  cmp $RESULT,0
  je @ERR_INIT_FAILED
mov emule_cmp_jcc,$RESULT		//!!!!
mov eip,oep
bp oep
ai
bc oep
////////////////////////
mov addr_cur,eip
@find_empty_space:
  find addr_cur,#00000000000000000000000000#
    cmp $RESULT,0
    je @end
  mov table_of_jcc,$RESULT
  mov addr_cur,$RESULT
  mov temp,$RESULT
  add temp,1A
  find temp,#00000000000000000000000000#
    cmp $RESULT,0
    je @end
  mov addr_cur,$RESULT
  cmp temp,$RESULT
jne @find_empty_space
////////////////////////

mov scan_end,FFFFFFFF
ask "Enter new base of this code"
cmp $RESULT,0
je @ERR_INIT_FAILED
mov base_new, $RESULT //006D1000
jmp @init_skip
ret
////////////////////////
@init_hand:
mov oep,eip				//  eip,   
mov call_VM	   	,00C00000	// !   
mov scan_start	   	,00B70CA1	// !   ( VM )
mov scan_end	   	,00B73FFE	// !   
mov base_old	   	,00B70000	// ! ,     
mov base_new	   	,0049A000	// !   ,    
mov table_of_jcc   	,00B72A00	// !   ,     jcc
mov emule_swich	   	,00AA88DA	// !  "SUB AL,2"      (jmp,call,...)
mov emule_type_jcc 	,00AA892D	// !  ,    
mov emule_jcc	   	,00AA893C	// !  "TEST AL,AL"  jcc
mov emule_cmp_get_arg1	,00AA8786	// !  ,  -       (1)
mov emule_cmp_get_arg2	,00AA87C2	// !  ,  -       (2)
mov emule_type_cmp	,00AA8805	// !  +3 (CMP EAX,4)    "CMP" 
mov emule_cmp_type_jcc	,00AA898D	// !  ,     ( cmp) 
mov emule_cmp_jcc	,00AA899C	// !  "TEST AL,AL"  jcc ( CMP)

mov emule_last_jamp	,00C10000	// !  ,   "JMP DWORD PTR SS:[ESP-4]"
@init_skip:
find emule_last_jamp,#FF6424FC#
cmp $RESULT,0
je @ERR_EMULE_LAST_JAMP_NOT_FOUND
mov emule_last_jamp,$RESULT

eval "Find VM call at [{scan_start}..{scan_end}].."
mov Info,$RESULT
log Info

/////////////////////////////////////////////////////////////////////////////////////////////
//      AsProtect'   //
/////////////////////////////////////////////////////////////////////////////////////////////
@find_VM_call:			//   VM 
  cmp scan_start,scan_end	// ,     
  ja @end			//  ,   
  find scan_start,#E8#		//   "call"
  cmp $RESULT,0			//    ,  
  je @end
  mov addr_cur,$RESULT		//    
  inc addr_cur			//   ,     
  mov scan_start,addr_cur	//    ,   
  mov temp,[addr_cur]		//    
  add temp,addr_cur		//   
  add temp,4			//    
  cmp temp,call_VM		//      
  jne @find_VM_call		//   ,  
  dec addr_cur			//    
  /////////[ DEBUG INFO ]/////////
  eval "Call found at {addr_cur}"
  mov Info,$RESULT
  log Info
  ////////////////////////////////
  mov eip,addr_cur		//  eip   VM 
  ////////////////////////////////
  cmp eip,00E41906
  jne @n
  //msg "pause!"
  @n:
  ////////////////////////////////
  jmp @rebuild_VM_call		//     
//end @find_VM_call
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
//      ,    //
//       //
//////////////////////////////////////////////////////////////////////////
@rebuild_VM_call:
  sub addr_cur,5		//   5    
  mov temp,[addr_cur]		// ,   
  and temp,000000FF		//     1 ,   0
  cmp temp,00000068		//    'PUSH'
  je @rebuild_push		//  ,     
  add addr_cur,5		//    VM 
 @trace_VM: 
  bp emule_swich		//       
  run				//  
  bc emule_swich		// ,  
  cmp eip,emule_swich		// ,   
  jne @ERR_BP_AT_SWICH_NOT_WORK	//  ,    

  mov emule_type_jcc_temp,emule_type_jcc
  mov emule_jcc_temp,emule_jcc
  mov table_of_jcc_base,table_of_jcc

  mov temp,eax			//    
  cmp temp,0			// 0 -  call
  je @trace_call_or_jmp		//    
  cmp temp,1			// 1 -  jmp
  je @trace_call_or_jmp		//    
  cmp temp,2			// 2 -  1  16  
  je @trace_jcc			//    jcc (jxx)
  cmp temp,3			// 3 -   2  - cmp + jcc
  je @trace_cmp_and_jcc		//    cmp + jcc
  msg "[Error!] Unknown emule command!"	//  -     
  jmp @find_VM_call		//    
//end @rebuild_VM_call
//////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////
//      ,  //
//    PUSH'      //
////////////////////////////////////////////////////////////
@rebuild_push:
  inc addr_cur				//    
  mov temp,[addr_cur]			//  
  //////[ DEBUG INFO ]//////
  eval "found PUSH {temp}"		
  mov Info,$RESULT
  log Info
  //////////////////////////
  sub temp,base_old			//     
  add temp,base_new			//   
  /////////[ DEBUG INFO ]//////////
  eval "converted to PUSH {temp}"
  mov Info,$RESULT
  log Info
  /////////////////////////////////
  mov [addr_cur],temp			//     
  add addr_cur,4			//  
  jmp @trace_VM				//  ,  .  
//end @rebuild_push
////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
//      "jmp"  "call"  //
//////////////////////////////////////////////////////////////////////////
@trace_call_or_jmp:			
  bp emule_last_jamp			//      VM
  run					//  
  bc emule_last_jamp			// ,  	
  cmp eip,emule_last_jamp		// ,   
  jne @ERR_BP_AT_EMULE_LAST_JAMP_NOT_WORK //  ,    
  mov temp,esp				//    
  sub temp,4				//   (esp-4)
  mov call_cur,[temp]			//   
  /////[ DEBUG INFO ]/////
  eval "Recovering 'jmp {call_cur}'..." 
  mov Info,$RESULT
  log Info
  ////////////////////////
  mov temp,addr_cur			//     
  cmp call_cur,base_old			// ,     
  jae @short_call			//  ,   
    sub temp,base_old			//     
    add temp,base_new			//   ,    
  @short_call:
  sub call_cur,temp			//      VM 
  sub call_cur,5			// 
  /// Debug!!!
  mov eip,addr_cur
  ////////////////
  //[   call 00XX0000 -> jmp XXXXXXXX ]//
  mov [addr_cur],E9			
  inc addr_cur				 
  mov [addr_cur],call_cur
  //////////////////////////////////////////////////////
  jmp @find_VM_call
//end @trace_call_or_jmp
//////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
//      "jcc" ( 16) //
///////////////////////////////////////////////////////////////////////////
@trace_jcc:
  bp emule_type_jcc_temp		//       . 
  run					//  
  bc emule_type_jcc_temp		// ,   
    cmp eip,emule_type_jcc_temp		// ,   
    jne @ERR_BP_AT_EMULE_TYPE_JCC_NOT_WORK//  ,    
  mov type_of_jcc,eax		//    
  bp emule_jcc_temp			//     
  run					//  
  bc emule_jcc_temp			// ,  
    cmp eip,emule_jcc_temp		//    
    jne @ERR_BP_AT_EMULE_JCC_NOT_WORK	//  ,    
  mov eax,1				//  eax  ,   
  bp emule_last_jamp			//    ,     
  run					//         
  bc emule_last_jamp			//    
    cmp eip,emule_last_jamp		// ,   
    jne @ERR_BP_AT_EMULE_LAST_JAMP_NOT_WORK //  ,    
  mov temp,esp				//    
  sub temp,4				//   (esp-4)
  mov call_cur,[temp]			//   
  					//
  cmp call_cur,base_old			// ,     
  jae @short_jcc			//  ,  
    mov temp,base_new			//    
    sub temp,call_addr			//      ,  
    add temp,base_old			//      
    mov call_cur,temp			//   
  @short_jcc:
    
//////////////////////////
//      //
//       //
//           //
//////////////////////////
  cmp type_of_jcc,0	//
  mov temp,"jo"		//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,1	//
  mov temp,"jno"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,2	//
  mov temp,"jb"		//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,3	//
  mov temp,"jnb"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,4	//
  mov temp,"je"		//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,5	//
  mov temp,"jnz"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,6	//
  mov temp,"jpe"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,7	//
  mov temp,"jpo"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,8	//
  mov temp,"js"		//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,9	//
  mov temp,"jns"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,A	//
  mov temp,"jbe"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,B	//
  mov temp,"ja"		//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,C	//
  mov temp,"jl"		//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,D	//
  mov temp,"jge"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,E	//
  mov temp,"jle"	//
  je @patch_table	//
//////////////////////////
  cmp type_of_jcc,F	//
  mov temp,"jg"		//
  je @patch_table	//
//////////////////////////

  //////////////////////////////////////////////////////////////////////////
  // ,      (2 ),      //
  //    ,        //
  //     ,   , ,   //
  //  EVAL              //
  //  ASM   OllyDbg     .    //
  //   :)........................................................//
  //////////////////////////////////////////////////////////////////////////

  @patch_table:			
  eval "{temp} {call_cur}"
  asm table_of_jcc,$RESULT	//    
  
  add table_of_jcc,6		//    = 6 
  mov eip,addr_cur		//    VM ,    

/////////////////////////////////////////////////
cmp emule_type_jcc_temp,emule_cmp_type_jcc
  jne @recover_jcc
////////////////////////
  bp emule_type_cmp
  run
  bc emule_type_cmp
    cmp eip,emule_type_cmp
    jne @ERR_BP_AT_EMULE_TYPE_CMP_NOT_WORK
  mov ebp,00400000
  add esp,10
  mov [esp],00400000
  sub esp,10
////////////////////////
  ////////////////////////////////////////////////////
 @recover_jcc:
  bp emule_jcc_temp			//      
  run					//  
  bc emule_jcc_temp			//   
  cmp eip,emule_jcc_temp		//    
  jne @ERR_BP_AT_EMULE_JCC_NOT_WORK	//      
  mov eax,0				//   0,    
  bp emule_last_jamp			//      
  run					//  
  bc emule_last_jamp			//    
  cmp eip,emule_last_jamp		// ,   
  jne @ERR_BP_AT_EMULE_LAST_JAMP_NOT_WORK //  ,    
  mov temp,esp				//    
  sub temp,4				//   (esp-4)
  mov call_cur,[temp]			//   

  cmp call_cur,base_old			// ,     
  jae @short_jmp			//  ,  
    mov temp,base_new			//    
    sub temp,call_addr			//    ,  
    add temp,base_old			//       
    mov call_cur,temp			//    
  @short_jmp:
  eval "jmp {call_cur}"			//    
  asm table_of_jcc,$RESULT		//   ( )
  
  /// Debug!!!
  mov eip,addr_cur
  /////////////
  mov temp,table_of_jcc_base		//      
  sub temp,addr_cur			//    VM 
  sub temp,5				// 
  mov [addr_cur],E9			//  call VM  jmp
  inc addr_cur				//    VM
  mov [addr_cur],temp			//   VM   . 
  dec addr_cur				// \ 
  add table_of_jcc,5			// / 
  //////////////////////////////////////////////////////
jmp @find_VM_call
//end @trace_jcc
//////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
//      (CMP)  5 //
///////////////////////////////////////////////////////////////////////////
@trace_cmp_and_jcc:
  
  mov table_of_jcc_base,table_of_jcc		//     
  bp emule_cmp_get_arg1				//    ,    
  run						//  
  bc emule_cmp_get_arg1				//    
   cmp eip,emule_cmp_get_arg1			// ,   
   jne @ERR_BP_AT_EMULE_CMP_GET_ARG1_NOT_WORK	//  ,    
  mov arg1_num,eax				//   
		
  bp emule_cmp_get_arg2				//    ,    
  run						//  
  bc emule_cmp_get_arg2				//    
   cmp eip,emule_cmp_get_arg2			// ,   
   jne @ERR_BP_AT_EMULE_CMP_GET_ARG1_NOT_WORK	//  ,    
  mov arg2_num,eax				//   
  bp emule_type_cmp				//      
  run						//  
  bc emule_type_cmp				//    
    cmp eip,emule_type_cmp			// ,   
    jne @ERR_BP_AT_EMULE_TYPE_CMP_NOT_WORK	//  ,    
  mov type_of_cmp,eax				//   CMP

 // CMP DWORD PTR DS:[????????],????????
 @case0:
  cmp type_of_cmp,0
  jne @case1
  mov str1,"cmp dword ptr ds:["  
  mov str2,"],"
  mov str3,""

  mov arg1_display,"eax"
  mov emule_cmp_size,2
  cmp arg1_num,0
  je  @0_calc_arg2

  mov arg1_display,"ecx"
  mov emule_cmp_size,2
  cmp arg1_num,1
  je  @0_calc_arg2

  mov arg1_display,"edx"
  mov emule_cmp_size,2
  cmp arg1_num,2
  je  @0_calc_arg2

  mov arg1_display,"ebx"
  mov emule_cmp_size,2
  cmp arg1_num,3
  je  @0_calc_arg2

  mov arg1_display,"esp"
  mov emule_cmp_size,3
  cmp arg1_num,4
  je  @0_calc_arg2

  mov arg1_display,"ebp"
  mov emule_cmp_size,3
  cmp arg1_num,5
  je  @0_calc_arg2

  mov arg1_display,"esi"
  mov emule_cmp_size,2
  cmp arg1_num,6
  je  @0_calc_arg2
  
  mov arg1_display,"edi"
  mov emule_cmp_size,2
  cmp arg1_num,7
  je  @0_calc_arg2

  mov arg1_display,ebp
  mov emule_cmp_size,6
 @0_calc_arg2:
  mov arg2_display,"eax"
  cmp arg2_num,0
  je  @end_switch
  
  mov arg2_display,"ecx"
  cmp arg2_num,1
  je  @end_switch

  mov arg2_display,"edx"
  cmp arg2_num,2
  je  @end_switch

  mov arg2_display,"ebx"
  cmp arg2_num,3
  je  @end_switch

  mov arg2_display,"esp"
  inc emule_cmp_size
  cmp arg2_num,4
  je  @end_switch
  dec emule_cmp_size

  mov arg2_display,"ebp"
  inc emule_cmp_size
  cmp arg2_num,5
  je  @end_switch
  dec emule_cmp_size

  mov arg2_display,"esi"
  cmp arg2_num,6
  je  @end_switch

  mov arg2_display,"edi"
  cmp arg2_num,7
  je  @end_switch

  mov arg2_display,esp
  add arg2_display,10
  mov arg2_display,[arg2_display]
  add emule_cmp_size,4
 
  jmp @end_switch
 // CMP ????????,DWORD PTR DS:[????????]
 @case1:  
  cmp type_of_cmp,1
  jne @case2
  mov str1,"cmp "  
  mov str2,",dword ptr ds:["
  mov str3,"]"

  mov arg1_display,"eax"
  mov emule_cmp_size,2
  cmp arg1_num,0
  je  @1_calc_arg2

  mov arg1_display,"ecx"
  mov emule_cmp_size,2
  cmp arg1_num,1
  je  @1_calc_arg2

  mov arg1_display,"edx"
  mov emule_cmp_size,2
  cmp arg1_num,2
  je  @1_calc_arg2

  mov arg1_display,"ebx"
  mov emule_cmp_size,2
  cmp arg1_num,3
  je  @1_calc_arg2

  mov arg1_display,"esp"
  mov emule_cmp_size,2
  cmp arg1_num,4
  je  @1_calc_arg2

  mov arg1_display,"ebp"
  mov emule_cmp_size,2
  cmp arg1_num,5
  je  @1_calc_arg2

  mov arg1_display,"esi"
  mov emule_cmp_size,2
  cmp arg1_num,6
  je  @1_calc_arg2
  
  mov arg1_display,"edi"
  mov emule_cmp_size,2
  cmp arg1_num,7
  je  @1_calc_arg2

  mov arg1_display,ebp
  mov emule_cmp_size,6
 @1_calc_arg2:
  mov arg2_display,"eax"
  cmp arg2_num,0
  je  @end_switch
  
  mov arg2_display,"ecx"
  cmp arg2_num,1
  je  @end_switch

  mov arg2_display,"edx"
  cmp arg2_num,2
  je  @end_switch

  mov arg2_display,"ebx"
  cmp arg2_num,3
  je  @end_switch

  mov arg2_display,"esp"
  cmp arg2_num,4
  je  @end_switch
  
  mov arg2_display,"ebp"
  cmp arg2_num,5
  je  @end_switch
  
  mov arg2_display,"esi"
  cmp arg2_num,6
  je  @end_switch

  mov arg2_display,"edi"
  cmp arg2_num,7
  je  @end_switch

  mov arg2_display,esp
  add arg2_display,10
  mov arg2_display,[arg2_display]
  add emule_cmp_size,4
  jmp @end_switch
  // CMP BYTE PTR DS:[????????],??
 @case2:
  cmp type_of_cmp,2
  jne @case3
  mov str1,"cmp byte ptr ds:["  
  mov str2,"],"
  mov str3,""

  mov arg1_display,"eax"
  mov emule_cmp_size,2
  cmp arg1_num,0
  je  @2_calc_arg2

  mov arg1_display,"ecx"
  mov emule_cmp_size,2
  cmp arg1_num,1
  je  @2_calc_arg2

  mov arg1_display,"edx"
  mov emule_cmp_size,2
  cmp arg1_num,2
  je  @2_calc_arg2

  mov arg1_display,"ebx"
  mov emule_cmp_size,2
  cmp arg1_num,3
  je  @2_calc_arg2

  mov arg1_display,"esp"
  mov emule_cmp_size,4
  cmp arg1_num,4
  je  @2_calc_arg2

  mov arg1_display,"ebp"
  mov emule_cmp_size,4
  cmp arg1_num,5
  je  @2_calc_arg2

  mov arg1_display,"esi"
  mov emule_cmp_size,2
  cmp arg1_num,6
  je  @2_calc_arg2
  
  mov arg1_display,"edi"
  mov emule_cmp_size,2
  cmp arg1_num,7
  je  @2_calc_arg2

  mov arg1_display,ebp
  mov emule_cmp_size,6
 @2_calc_arg2:
  mov arg2_display,"al"
  cmp arg2_num,0
  je  @end_switch
  
  mov arg2_display,"cl"
  cmp arg2_num,1
  je  @end_switch

  mov arg2_display,"dl"
  cmp arg2_num,2
  je  @end_switch

  mov arg2_display,"bl"
  cmp arg2_num,3
  je  @end_switch

  mov arg2_display,"??"
  cmp arg2_num,4
  je  @ERR_EMULE_ARG
  
  mov arg2_display,"??"
  cmp arg2_num,5
  je  @ERR_EMULE_ARG
  
  mov arg2_display,"??"
  cmp arg2_num,6
  je  @ERR_EMULE_ARG

  mov arg2_display,"??"
  cmp arg2_num,7
  je  @ERR_EMULE_ARG

  mov arg2_display,esp
  add arg2_display,10
  mov arg2_display,[arg2_display]
  add emule_cmp_size,1
  jmp @end_switch
  // CMP ??,BYTE PTR DS:[????????]
 @case3:
  cmp type_of_cmp,3
  jne @case4
  mov str1,"cmp "  
  mov str2,",byte ptr ds:["
  mov str3,"]"

  mov arg1_display,"al"
  mov emule_cmp_size,2
  cmp arg1_num,0
  je  @3_calc_arg2

  mov arg1_display,"cl"
  mov emule_cmp_size,2
  cmp arg1_num,1
  je  @3_calc_arg2

  mov arg1_display,"dl"
  mov emule_cmp_size,2
  cmp arg1_num,2
  je  @3_calc_arg2

  mov arg1_display,"bl"
  mov emule_cmp_size,2
  cmp arg1_num,3
  je  @3_calc_arg2

  mov arg1_display,"??"
  mov emule_cmp_size,2
  cmp arg1_num,4
  je  @3_calc_arg2

  mov arg1_display,"??"
  mov emule_cmp_size,2
  cmp arg1_num,5
  je  @3_calc_arg2

  mov arg1_display,"??"
  mov emule_cmp_size,2
  cmp arg1_num,6
  je  @3_calc_arg2
  
  mov arg1_display,"??"
  mov emule_cmp_size,2
  cmp arg1_num,7
  je  @3_calc_arg2

  mov arg1_display,ebp
  mov emule_cmp_size,6
 @3_calc_arg2:
  mov arg2_display,"eax"
  cmp arg2_num,0
  je  @end_switch
  
  mov arg2_display,"ecx"
  cmp arg2_num,1
  je  @end_switch

  mov arg2_display,"edx"
  cmp arg2_num,2
  je  @end_switch

  mov arg2_display,"ebx"
  cmp arg2_num,3
  je  @end_switch

  mov arg2_display,"esp"
  cmp arg2_num,4
  je  @end_switch
  
  mov arg2_display,"ebp"
  cmp arg2_num,5
  je  @end_switch
  
  mov arg2_display,"esi"
  cmp arg2_num,6
  je  @end_switch

  mov arg2_display,"edi"
  cmp arg2_num,7
  je  @end_switch

  mov arg2_display,esp
  add arg2_display,10
  mov arg2_display,[arg2_display]
  add emule_cmp_size,1
  jmp @end_switch
  // CMP ????????,????????
 @case4:
  cmp type_of_cmp,4
  jne @ERR_UNKNOWN_TYPE_CMP
  mov str1,"cmp "  
  mov str2,","
  mov str3,""

  mov arg1_display,"eax"
  mov emule_cmp_size,2
  cmp arg1_num,0
  je  @4_calc_arg2

  mov arg1_display,"ecx"
  mov emule_cmp_size,2
  cmp arg1_num,1
  je  @4_calc_arg2

  mov arg1_display,"edx"
  mov emule_cmp_size,2
  cmp arg1_num,2
  je  @4_calc_arg2

  mov arg1_display,"ebx"
  mov emule_cmp_size,2
  cmp arg1_num,3
  je  @4_calc_arg2

  mov arg1_display,"esp"
  mov emule_cmp_size,2
  cmp arg1_num,4
  je  @4_calc_arg2

  mov arg1_display,"ebp"
  mov emule_cmp_size,2
  cmp arg1_num,5
  je  @4_calc_arg2

  mov arg1_display,"esi"
  mov emule_cmp_size,2
  cmp arg1_num,6
  je  @4_calc_arg2
  
  mov arg1_display,"edi"
  mov emule_cmp_size,2
  cmp arg1_num,7
  je  @4_calc_arg2

  mov arg1_display,ebp
  mov emule_cmp_size,5
 @4_calc_arg2:
  mov arg2_display,"eax"
  cmp arg2_num,0
  je  @end_switch
  
  mov arg2_display,"ecx"
  cmp arg2_num,1
  je  @end_switch

  mov arg2_display,"edx"
  cmp arg2_num,2
  je  @end_switch

  mov arg2_display,"ebx"
  cmp arg2_num,3
  je  @end_switch

  mov arg2_display,"esp"
  cmp arg2_num,4
  je  @end_switch
  
  mov arg2_display,"ebp"
  cmp arg2_num,5
  je  @end_switch
  
  mov arg2_display,"esi"
  cmp arg2_num,6
  je  @end_switch

  mov arg2_display,"edi"
  cmp arg2_num,7
  je  @end_switch

  mov arg2_display,esp
  add arg2_display,10
  mov arg2_display,[arg2_display]
  add emule_cmp_size,4
 
  jmp @end_switch
//////////////////////////////////////////////////////////////////////////////////////
 @end_switch:
  eval "{str1}{arg1_display}{str2}{arg2_display}{str3}"
  asm table_of_jcc,$RESULT
  add table_of_jcc,emule_cmp_size
  ///////////////
  mov ebp,00400000
  add esp,10
  mov [esp],00400000
  sub esp,10
  
  mov emule_type_jcc_temp,emule_cmp_type_jcc
  mov emule_jcc_temp,emule_cmp_jcc
  jmp @trace_jcc
  ///////////////
  pause  

@end:
mov eip,oep
log "____________________________________"
ret

@ERR_BP_AT_SWICH_NOT_WORK:
msg "[Error!] BreakPoint at emule_swich not work!"
jmp @end

@ERR_BP_AT_EMULE_LAST_JAMP_NOT_WORK:
msg "[Error!] BreakPoint at emule_last_jamp not work!"
jmp @end

@ERR_BP_AT_EMULE_TYPE_JCC_NOT_WORK:
msg "[Error!] BreakPoint at emule_type_jcc not work!"
jmp @end

@ERR_BP_AT_EMULE_JCC_NOT_WORK:
msg "[Error!] BreakPoint at emule_jcc not work!"
jmp @end

@ERR_BP_AT_EMULE_CMP_GET_ARG1_NOT_WORK:
msg "[Error!] BreakPoint at emule_cmp_get_argX not work!"
jmp @end

@ERR_BP_AT_EMULE_TYPE_CMP_NOT_WORK:
msg "[Error!] BreakPoint at emule_type_cmp not work!"
jmp @end

@ERR_BP_AT_EMULE_CMP_NOT_WORK:
msg "[Error!] BreakPoint at emule_cmp not work!"
jmp @end

@ERR_BP_AT_EMULE_CMP_TYPE_JCC_NOT_WORK:
msg "[Error!] BreakPoint at emule_cmp_type_jcc not work!"
jmp @end

@ERR_EMULE_LAST_JAMP_NOT_FOUND:
msg "[Error!] Command 'JMP DWORD PTR SS:[ESP-4]' not found!"
jmp @end

@ERR_VM_CALL_NOT_FOUND:
msg "[Error!] VM call not found!"
jmp @end

@ERR_INIT_FAILED:
msg "[Error!] Init failed!"
jmp @end

@ERR_EMULE_ARG:
msg "[Error!] Register not found!"
jmp @end

@ERR_UNKNOWN_TYPE_CMP:
msg "[Error!] Unknown type of cmp instruction!"
jmp @end